#!/bin/sh
#(c) Copyright Barry Kauler 2012, bkhome.org
#License GPL3 (/usr/share/doc/legal)
#shared-mime-info pkg has assigned initrd.gz mime-type application/initramfs-gz (by me).
#Click on initrd.gz/xz in a file manager, this script will run (see ${HOME}/Choices/MIME-types/application_initramfs-gz).
#note: script not internationalized, as this is a developer's tool.

zhelp() {
	script=${0##*/} ; echo "
Usage:

       $script -x|-c <initrd.gz/xz>
          -x: extract
          -c: compress"
	exit
}

#find out compression type...
function compr_func() {
	comp="$(file -b "$1")"
	case "$comp" in
		gz*|GZ*) UNCOMPREXE=gunzip ; EXT=gz ; COMPREXE=gzip ;;
		xz*|XZ*) UNCOMPREXE=unxz   ; EXT=xz ; COMPREXE='xz --check=crc32 --lzma2' ;;
		*cpio*|*CPIO*) CPIO=1 ;; #fd64
		*) echo "Unsupported compression/format for initrd."
			exit 1 ;;
	esac
}

#find out partition filesystem a file is located in
function FILE_FS_IS_OK() {
	[ $FILE_FS_IS_OK ] && return $FILE_FS_IS_OK
	local MOUNTPOINT="$(stat -c '%m' "$@")"
	local FS="$(mount | grep " $MOUNTPOINT " | cut -f 5 -d ' ')"
	case $FS in
		ext*|rootfs) FILE_FS_IS_OK=0 ;;
		*) FILE_FS_IS_OK=1 ;;
	esac
	return $FILE_FS_IS_OK
}

##################################################
# CLI (to extract and recompress in the same dir)
##################################################

function initrd_proc() { #<extract|compress> [-home] <initrd.gz/xz>

	OPTION=$1
	shift
	[ "$1" = "-home" ] && { TOHOME=1; shift; }

	INFILE="$@"
	case $INFILE in
		*'initrd-expanded')
			INITRD_DIR=1
			[ -e "$INFILE" ] || { echo "ERROR: file does not exist: $INFILE"; exit 1; }
			INFILE=$(dirname $INFILE)/initrd.gz
			UNCOMPREXE=gunzip EXT=gz COMPREXE=gzip
			;;
		*)
			[ -f "$INFILE" ] || { echo "ERROR: file does not exist: $INFILE"; exit 1; }
			[[ $INFILE != /* ]] && INFILE=$PWD/$INFILE
			;;
	esac
	DIR="`dirname "$INFILE"`"
	FILE_NAME=${INFILE##*/}

	CURDIRX=$DIR
	FILE_FS_IS_OK "$DIR" || TOHOME=1
	[ $TOHOME ] && DIR=${HOME}

	cd "$DIR"

	## now proceed
	if [ ! "$INITRD_DIR" -o "$CPIO" != "" ] ; then
		[ $TOHOME ] && cp -fv "$INFILE" ${HOME}
		[ -f initrd -o -f initrd.gz -o -f initrd.xz ] || { echo "initrd.gz/xz not found in $DIR" ; exit 1 ; }
		compr_func ${FILE_NAME} || { echo "ERROR getting compression type for ${FILE_NAME}" >&2 ; return 1 ; }
	fi

	if [ "$OPTION" = "extract" ] ; then
		echo "Expanding at $DIR"
		if [ "$CPIO" = "" ] ; then
			[ "initrd.${EXT}" != "${FILE_NAME}" ] && cp -f "${FILE_NAME}" initrd.${EXT}
			#-f and -k are options in gunzip, and unxz
			zout=$($UNCOMPREXE -f -k initrd.${EXT} 2>&1)
			if [ $? -ne 0 ] ; then
				echo -e "${comp}\n${zout}" >&2
				rm -f initrd.${EXT}
				return 5 #error extracting
			fi
		fi
		mkdir -p initrd-expanded
		cd initrd-expanded
		cat ../initrd | cpio -i -d -m
		rm -f ../initrd
		cd ..
		[ "initrd.${EXT}" != "${FILE_NAME}" ] && rm -f initrd.${EXT}
		[ "$TOHOME" ] && rm -f ${HOME}/${FILE_NAME}
		return 0
	else #compress
		echo "Creating $FILE_NAME from $DIR"
		[ -d initrd-expanded ] || { echo "'initrd-expanded' not found in $DIR" ; exit 1 ; }
		cd initrd-expanded
		find . | cpio -o -H newc > ../initrd
		cd ..
		${COMPREXE} -f initrd
		[ "initrd.${EXT}" != "${FILE_NAME}" ] && mv -f initrd.${EXT} "${FILE_NAME}"
		[ "$TOHOME" -a "$HOME" != "$CURDIRX" ] && mv -fv ${FILE_NAME} "$CURDIRX"
		return 0
	fi
}

#================================================

case $1 in
	-x) shift ; initrd_proc extract "$@" ; exit $? ;;
	-c) shift ; initrd_proc compress "$@" ; exit $? ;;
	-h|-help|--help) zhelp ; exit $? ;;
esac

[ $DISPLAY ] || zhelp

##################################################
#					GUI
##################################################

zfile="$1"
[ ! -f "$zfile" ] && exit 1
[[ $zfile != /* ]] && zfile=$PWD/$zfile
DIRX="`dirname "$zfile"`"
BASEFILE="`basename "$zfile"`"

case "${BASEFILE}" in
	*initrd|*"initrd.gz"|*"initrd.xz") ok=1 ;;
	*) exit 1 ;;
esac

cd ${HOME}
[ -f initrd ] && rm -f initrd
[ -f /tmp/${BASEFILE} ] && rm -f /tmp/${BASEFILE}
[ "$zfile" = "${HOME}/${BASEFILE}" ] && cp -f ${HOME}/${BASEFILE} /tmp/

if [ -d "${HOME}/initrd-expanded" ] ; then
	ex1="An ${BASEFILE} is already expanded at ${HOME}/initrd-expanded.\n\n"
	msgx="Is this correct, do you want to use ${HOME}/initrd-expanded to update ${zfile}?"
	expanded_home=1
fi

if [ -d "$DIRX/initrd-expanded" ] ;then
	if FILE_FS_IS_OK "$DIRX/initrd-expanded" ; then
		ex2="An ${BASEFILE} is already expanded at $DIRX/initrd-expanded.\n\n"
		msgx="Is this correct, do you want to use $DIRX/initrd-expanded to update ${zfile}?"
		expanded_dir=1
	fi
fi

if [ "$expanded_home" -a "$expanded_dir" ] ; then
	msgx="Please choose one of the above dirs to update ${BASEFILE}"
fi

EXP_DIR=$DIRX/initrd-expanded

if [ "$expanded_home" -o "$expanded_dir" ] ; then ### COMPRESS ###

	if [ "$expanded_home" -a "$expanded_dir" ] ; then
		#initrd-expanded is in both ${HOME} and $DIRX
		pupdialog --colors --background '#FFFF80' \
		--backtitle "${BASEFILE}: expand?" --extra-button \
		--yes-label "${HOME}" \
		--extra-label "$DIRX" \
		--no-label "Cancel" \
		--yesno "$ex1 $ex2 $msgx" 0 0
		retval=$?
		case $retval in
			0) toHOME="-home" ; EXP_DIR=${HOME}/initrd-expanded;; #"${HOME}"
			3) EXP_DIR=$DIRX/initrd-expanded ;; #"$DIRX"
			*) exit ;; #"Cancel"
		esac
	else
		#initrd-expanded is in ${HOME} OR $DIRX
		pupdialog --background "yellow" --backtitle "${BASEFILE}: update?" \
		--yesno "$ex1 $ex2 $msgx" 0 0
		[ $? -ne 0 ] && exit
		if [ "$expanded_home" ] ; then
			toHOME="-home"
			EXP_DIR=${HOME}/initrd-expanded
		fi
	fi

	initrd_proc compress $toHOME "$zfile"
	pupdialog --background '#80FF80' --backtitle "${BASEFILE}: success" --msgbox "File ${zfile} has been updated with the contents of ${EXP_DIR}." 0 0
	[ $toHOME ] || exit
	pupdialog --background "yellow" --backtitle "${BASEFILE}: finished" --yesno "Do you want to delete ${HOME}/initrd-expanded? If in doubt, please choose Yes" 0 0
	if [ $? -eq 0 ] ; then
		rox -D ${HOME}/initrd-expanded 2>/dev/null
		rm -rf ${HOME}/initrd-expanded
	fi
  
else ### EXPAND ###

	if FILE_FS_IS_OK "$DIRX" ; then
		pupdialog --colors --background '#FFFF80' \
		--backtitle "${BASEFILE}: expand?" --extra-button \
		--yes-label "Expand at ${HOME}" \
		--extra-label "Expand at Current dir" \
		--no-label "Cancel" \
		--yesno "Current dir:\n ${DIRX}\n\nDo you want to open up ${BASEFILE}, and optionally edit it?\n\n" 0 0
		retval=$?
		case $retval in
			0) toHOME="-home" ; EXP_DIR=${HOME}/initrd-expanded;; #"expand at ${HOME}"
			3) EXP_DIR=$DIRX/initrd-expanded ;; #"Expand at ${BASEFILE} dir"
			*) exit ;; #"Cancel"
		esac
	else
		msg="Do you want to open up ${BASEFILE}, and optionally edit it?\n\n"
		pupdialog --colors --background '#FFFF80' --backtitle "${BASEFILE}: expand?" --yes-label "Expand at ${HOME}" --no-label "Cancel" --yesno "$msg" 0 0
		[ $? -ne 0 ] && exit
		if [ "$expanded_home" ] ; then
			toHOME="-home"
			EXP_DIR=${HOME}/initrd-expanded
		fi
	fi

	initrd_proc extract $toHOME "$zfile"
	[ $? -eq 5 ] && exec pupdialog --colors --background '#FF2222' --backtitle "ERROR" --msgbox "error extracting initrd.${EXT}\n\n${comp}\n\n${zout}" 0 0
	pupdialog --colors --background '#80FF80' --backtitle "${BASEFILE}: expanded" --msgbox "File ${BASEFILE} has been expanded at \Zb${EXP_DIR}\ZB. You may edit the contents if you wish. \Zb\Z1\n\nAfterward, if you click on ${zfile} again\Zn\ZB, it will be updated with the contents of ${EXP_DIR}." 0 0
	[ $toHOME ] && rox ${EXP_DIR}

fi

[ -f /tmp/${BASEFILE} ] && rm -f /tmp/${BASEFILE}

### END ###
